﻿namespace CoProjectDF.Views.Login
{
    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;

    /// <summary>
    /// Form that presents the login fields and handles the login process.
    /// </summary>
    public partial class LoginForm : StackPanel
    {
        private LoginRegistrationWindow parentWindow;
        private LoginViewModel loginViewModel;

        /// <summary>
        /// Creates a new <see cref="LoginForm"/> instance.
        /// </summary>
        public LoginForm()
        {
            InitializeComponent();
            this.DataContext = loginViewModel = new LoginViewModel();
        }

        /// <summary>
        /// Sets the parent window for the current <see cref="LoginForm"/>.
        /// </summary>
        /// <param name="window">The window to use as the parent.</param>
        public void SetParentWindow(LoginRegistrationWindow window)
        {
            this.parentWindow = window;
        }

        /// <summary>
        /// Called by the parent window when close/cancel is wanted.
        /// </summary>
        /// <returns></returns>
        public bool CanClose()
        {
            if (!loginViewModel.CanCancel) return false;
            loginViewModel.Cancel();
            this.loginForm.CancelEdit();
            return true;
        }

        /// <summary>
        /// Handles <see cref="DataForm.AutoGeneratingField"/> to provide the PasswordAccessor.
        /// </summary>
        private void LoginForm_AutoGeneratingField(object sender, DataFormAutoGeneratingFieldEventArgs e)
        {
            e.Field.Mode = DataFieldMode.AddNew;
            if (e.PropertyName == "Password")
            {
                PasswordBox passwordBox = (PasswordBox)e.Field.Content;
                loginViewModel.SetPasswordAccessor(() => passwordBox.Password);
            }
        }

        /// <summary>
        /// Submits the login request.
        /// </summary>
        private void LoginButton_Click(object sender, EventArgs e)
        {

            // We need to force validation since we are not using the standard OK
            // button from the DataForm.  Without ensuring the form is valid, we
            // would get an exception invoking the operation if the entity is invalid.
            if (this.loginForm.ValidateItem())
            {
                //loginViewModel.Login(LoginCompleted);
                //Updated to provide failure handling differently when using loginAsync
                //which does not return any values on success.
                loginViewModel.Login(LoginCompleted, LoginFailed);
            }
        }

        /// <summary>
        /// Login completion handler.  Supply a general message for login failure; if the login succeeded
        /// close the window.
        /// </summary>
        /// <param></param>
        private void LoginCompleted()
        {
            this.parentWindow.Close();
            loginViewModel.UpdateState();
        }

        /// <summary>
        /// Login failure handler. Do not close window and show error to user.
        /// </summary>
        /// <param name="exception"></param>
        private void LoginFailed(Exception ex)
        {
            if (ex != null)
            {
                status.Text = ex.Message;
            }

            loginViewModel.UpdateState();
        }

        /// <summary>
        /// Switches to the registration form.
        /// </summary>
        private void RegisterNow_Click(object sender, RoutedEventArgs e)
        {
            this.parentWindow.NavigateToRegistration();
        }

        /// <summary>
        /// Cancel if possible and close window.
        /// </summary>
        private void CancelButton_Click(object sender, EventArgs e)
        {
            this.parentWindow.Close();
        }

        /// <summary>
        /// Maps Esc to the cancel button and Enter to the OK button.
        /// </summary>
        private void LoginForm_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Escape)
            {
                this.CancelButton_Click(sender, e);
            }
            else if (e.Key == Key.Enter && this.loginButton.IsEnabled)
            {
                this.LoginButton_Click(sender, e);
            }
        }
    }
}
